<?php
// TODO: create SQLConditionsGroupClause. make all methods using SQLConditionsClause be compatible with this
/**
 * Builds up a programmatic model for SQL WHERE clause to be used by SELECT, UPDATE, DELETE queries.
 */
class SQLConditionsClause extends AbstractSQLClause {
	protected $strCurrentLogicalOperator = SQLLogicalOperators::_AND_;
	
	public static function getInstance() {
		return new SQLConditionsClause();
	}
	
	/**
	 * Sets up an =/IN clause directly from constructor. 
	 * 
	 * @example array("a"=>new SQLValue("b"))
	 * @param array $tblConditions
	 */
	public function __construct($tblConditions=array()) {
		if(sizeof($tblConditions)) {
			foreach($tblConditions as $key=>$value) {
				if(is_array($value)) {
					$this->setIn($key, $value);
				} else {
					$this->set($key, $value);
				}
			}
		}
	}
	
	/**
	 * Adds a field vs. value condition. Default is field = value.
	 *  
	 * @example ("a", "b", SQLComparisonOperators::DIFFERS)
	 * @param SQLValue|string $key
	 * @param SQLValue|string $value
	 * @param SQLComparisonOperators $strComparisonOperator
	 * @return SQLConditionsClause
	 */
	public function set($key, $value, $strComparisonOperator=SQLComparisonOperators::EQUALS) {
		$tblClause = array();
		$tblClause["KEY"]=$key;
		$tblClause["COMPARATOR"]=$strComparisonOperator;
		$tblClause["VALUE"]=$value;
		$this->tblContents[]=$tblClause;
		return $this;
	}
	
	/**
	 * Adds an "IN/NOT IN" condition. 
	 * 
	 * @example ("c", array(new SQLValue("d'w"),"e"),true)
	 * @param SQLValue|string $key
	 * @param array(SQLValue|string) $tblValues
	 * @param boolean $blnIsTrue
	 * @return SQLConditionsClause
	 */
	public function setIn($key, $tblValues, $blnIsTrue=true) {
		$tblClause = array();
		$tblClause["KEY"]=$key;
		$tblClause["COMPARATOR"]=($blnIsTrue?SQLComparisonOperators::IN:SQLComparisonOperators::NOT_IN);
		$tblClause["VALUE"]=$tblValues;		
		$this->tblContents[]=$tblClause;
		return $this;
	}
	
	/**
	 * Adds a "NULL/NOT NULL" condition.
	 * 
	 * @example ("f", false)
	 * @param SQLValue|string $key
	 * @param boolean $blnIsTrue
	 * @return SQLConditionsClause
	 */
	public function setNull($key, $blnIsTrue=true) {
		$tblClause = array();
		$tblClause["KEY"]=$key;
		$tblClause["COMPARATOR"]=($blnIsTrue?SQLComparisonOperators::IS_NULL:SQLComparisonOperators::IS_NOT_NULL);
		$this->tblContents[]=$tblClause;
		return $this;
	}
	
	/**
	 * Sets up a "LIKE/NOT LIKE" condition.
	 * 
	 * @example ("g", new SQLValue("%h"))
	 * @param SQLValue|string $key
	 * @param string $pattern
	 * @param boolean $blnIsLike
	 * @return SQLConditionsClause
	 */
	public function setLike($key, $pattern, $blnIsTrue=true) {
		$tblClause = array();
		$tblClause["KEY"]=$key;
		$tblClause["COMPARATOR"]=($blnIsTrue?SQLComparisonOperators::LIKE:SQLComparisonOperators::NOT_LIKE);
		$tblClause["VALUE"]=$pattern;
		$this->tblContents[]=$tblClause;
		return $this;
	}
	
	/**
	 * Sets up a "BETWEEN/NOT BETWEEN" condition.
	 * 
	 * @example ("i","j","k",false)
	 * @param SQLValue|string $key
	 * @param SQLValue|string $valueLeft
	 * @param SQLValue|string $valueRight
	 * @param boolean $blnIsBetween
	 * @return SQLConditionsClause
	 */
	public function setBetween($key, $valueLeft, $valueRight, $blnIsTrue=true) {
		$tblClause = array();
		$tblClause["KEY"]=$key;
		$tblClause["COMPARATOR"]=($blnIsTrue?SQLComparisonOperators::BETWEEN:SQLComparisonOperators::NOT_BETWEEN);
		$tblClause["VALUE_LEFT"]=$valueLeft;
		$tblClause["VALUE_RIGHT"]=$valueRight;
		$this->tblContents[]=$tblClause;
		return $this;
	}
	
	/**
	 * Transforms clause to string.
	 * 
	 * @example a<>b AND c IN ('d''w',e) AND f IS NOT NULL AND g LIKE '%h' AND i NOT BETWEEN j AND k
	 * (non-PHPdoc)
	 * @see AbstractSQLClause::toString()
	 */
	public function toString() {
		$output = "";		
		foreach($this->tblContents as $tblValues) {			
			// create condition
			if($tblValues["COMPARATOR"] == SQLComparisonOperators::IS_NULL || $tblValues["COMPARATOR"] == SQLComparisonOperators::IS_NOT_NULL) {
				$output .= $this->getValue($tblValues["KEY"])." ".$tblValues["COMPARATOR"];
			} else if($tblValues["COMPARATOR"] == SQLComparisonOperators::BETWEEN || $tblValues["COMPARATOR"] == SQLComparisonOperators::NOT_BETWEEN) {
				$output .= $this->getValue($tblValues["KEY"])." ".$tblValues["COMPARATOR"]." ".$this->getValue($tblValues["VALUE_LEFT"])." AND ".$this->getValue($tblValues["VALUE_RIGHT"]);
			} else if($tblValues["COMPARATOR"] == SQLComparisonOperators::IN || $tblValues["COMPARATOR"] == SQLComparisonOperators::NOT_IN) {
				$tblTMP = $tblValues["VALUE"];
				$strValues = "";
				foreach($tblTMP as $strString) {
					$strValues .= $this->getValue($strString).",";
				}
				$output .= $this->getValue($tblValues["KEY"])." ".$tblValues["COMPARATOR"]." (".substr($strValues,0,-1).")";
			} else {
				$output .= $this->getValue($tblValues["KEY"])." ".$tblValues["COMPARATOR"]." ".$this->getValue($tblValues["VALUE"]);
			}
			
			$output .=" ".$this->strCurrentLogicalOperator." ";
		}
		return substr($output,0, -5);
	}
}